<?php
namespace app\common\service\Poster;

class DoctorPoster
{
    // 画布尺寸（手机分享图适配）
    private $W = 750;      // px
    private $H = 1100;

    private $fonts;

    public function __construct()
    {
        $fontDir = ROOT_PATH . 'public/fonts/';
        $this->fonts = [
            'regular' => '/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc',
            'medium'  => '/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc',
            'bold'    => '/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc',
        ];
        foreach ($this->fonts as $f) {
            if (!file_exists($f)) {
                throw new \RuntimeException('缺少字体文件：' . $f);
            }
        }
    }

    /** 生成并返回文件路径（带 24h 缓存） */
    public function make(array $d): string
    {
        $saveDir = ROOT_PATH . 'public/uploads/poster/doctor/';
        if (!is_dir($saveDir)) mkdir($saveDir, 0775, true);
        $file = $saveDir . "doctor_{$d['id']}.png";

        if (file_exists($file) && (time() - filemtime($file) < 86400)) {
            return $file;
        }

        // 1) 画布&底色
        $im = imagecreatetruecolor($this->W, $this->H);
        $bg = $this->color($im, [246, 249, 252]);
        imagefill($im, 0, 0, $bg);

        // 2) 主卡片（圆角）
        $card = [
            'x' => 24, 'y' => 24, 'w' => $this->W - 48, 'h' => 760, 'r' => 24
        ];
        $this->roundedRect($im, $card, [255, 255, 255]);

        // 3) 顶部绿色区块
        $header = ['x' => $card['x'], 'y' => $card['y'], 'w' => $card['w'], 'h' => 300, 'r' => 24];
        $this->roundedRect($im, $header, [12, 175, 158]);

        // 4) 医院名
        $this->ttf($im, 24, $card['x'] + 28, $card['y'] + 60, '#ffffff', $this->fonts['medium'], $d['hospital']);

        // 5) 医生姓名 + 头像
        $this->ttf($im, 52, $card['x'] + 28, $card['y'] + 140, '#ffffff', $this->fonts['bold'], $d['name']);
        // 头像：右上角圆裁剪
        if (is_file($d['avatar'])) {
            $this->drawCircleImage(
                $im, $d['avatar'],
                $card['x'] + $card['w'] - 28 - 160, $card['y'] + 40, // x,y
                160, 160                                               // w,h
            );
        }

        // 6) 职称 + 医院 + 等级标签
        $this->ttf($im, 26, $card['x'] + 28, $card['y'] + 190, '#dcfff9', $this->fonts['regular'], $d['title']);
        $this->ttf($im, 26, $card['x'] + 28, $card['y'] + 230, '#dcfff9', $this->fonts['regular'], $d['hospital']);
        $this->badge($im, $card['x'] + 300, $card['y'] + 202, '三甲', [255,255,255], [12,175,158]);

        // 7) 星级 + 接诊量 / 粉丝量
        $starY = $card['y'] + 280;
        $this->drawStarRow($im, $card['x'] + 28, $starY, 5, $d['score']);
        $this->ttf($im, 28, $card['x'] + 220, $starY, '#ffffff', $this->fonts['medium'], "接诊量  {$d['consult_cnt']}  /  粉丝量  {$d['fans_cnt']}");

        // 8) 简介 & 擅长
        $padX = $card['x'] + 28;
        $textTop = $card['y'] + 330;
        $this->ttf($im, 28, $padX, $textTop, '#10b981', $this->fonts['medium'], '简介：');
        $intro = $this->wrap($d['intro'], $this->fonts['regular'], 26, $card['w'] - 56, 3);
        $this->ttf($im, 26, $padX + 70, $textTop, '#374151', $this->fonts['regular'], $intro);

        $textTop += 160;
        $this->ttf($im, 28, $padX, $textTop, '#10b981', $this->fonts['medium'], '擅长：');
        $goodat = $this->wrap($d['good_at'], $this->fonts['regular'], 26, $card['w'] - 56, 3);
        $this->ttf($im, 26, $padX + 70, $textTop, '#374151', $this->fonts['regular'], $goodat);

        // 9) 底部医院名 + 小程序码
        $baseY = $card['y'] + $card['h'] - 200;
        $this->ttf($im, 36, $padX, $baseY, '#111827', $this->fonts['bold'], $d['hospital']);
        $this->ttf($im, 24, $padX, $baseY + 60, '#6b7280', $this->fonts['regular'], '长按图片识别  前往小程序了解医生详情');

        if (is_file($d['qrcode'])) {
            $this->drawImage($im, $d['qrcode'], $card['x'] + $card['w'] - 200, $baseY - 30, 160, 160);
        }

        // 10) 导出：PNG + 轻压缩
        imagepng($im, $file);
        imagedestroy($im);
        return $file;
    }

    /* ----------------- 绘图工具 ----------------- */

    private function color($im, array $rgb) { return imagecolorallocate($im, $rgb[0], $rgb[1], $rgb[2]); }

    private function hex2rgb($hex){
        $hex = ltrim($hex, '#'); if(strlen($hex)==3){$hex=$hex[0].$hex[0].$hex[1].$hex[1].$hex[2].$hex[2];}
        return [hexdec(substr($hex,0,2)),hexdec(substr($hex,2,2)),hexdec(substr($hex,4,2))];
    }

    private function ttf($im, $size, $x, $y, $color, $font, $text){
        $rgb = is_array($color) ? $color : $this->hex2rgb($color);
        $col = $this->color($im, $rgb);
        imagettftext($im, $size, 0, $x, $y, $col, $font, $text);
    }

    private function roundedRect($im, $box, array $rgb){
        // 画圆角矩形填充
        $col = $this->color($im, $rgb);
        $x=$box['x']; $y=$box['y']; $w=$box['w']; $h=$box['h']; $r=$box['r'];
        imagefilledrectangle($im, $x+$r, $y, $x+$w-$r, $y+$h, $col);
        imagefilledrectangle($im, $x, $y+$r, $x+$w, $y+$h-$r, $col);
        imagefilledellipse($im, $x+$r, $y+$r, $r*2, $r*2, $col);
        imagefilledellipse($im, $x+$w-$r, $y+$r, $r*2, $r*2, $col);
        imagefilledellipse($im, $x+$r, $y+$h-$r, $r*2, $r*2, $col);
        imagefilledellipse($im, $x+$w-$r, $y+$h-$r, $r*2, $r*2, $col);
    }

    private function drawImage($im, $path, $x, $y, $w, $h){
        $src = $this->createFrom($path); if(!$src) return;
        $srcW = imagesx($src); $srcH = imagesy($src);
        imagecopyresampled($im, $src, $x, $y, 0, 0, $w, $h, $srcW, $srcH);
        imagedestroy($src);
    }

    private function drawCircleImage($im, $path, $x, $y, $w, $h){
        $src = $this->createFrom($path); if(!$src) return;
        $srcW = imagesx($src); $srcH = imagesy($src);

        // 先缩放
        $tmp = imagecreatetruecolor($w, $h);
        imagealphablending($tmp, false); imagesavealpha($tmp, true);
        $trans = imagecolorallocatealpha($tmp, 0,0,0,127); imagefill($tmp,0,0,$trans);
        imagecopyresampled($tmp, $src, 0,0,0,0, $w,$h, $srcW,$srcH);

        // 创建圆形蒙版
        $mask = imagecreatetruecolor($w, $h);
        imagealphablending($mask, false); imagesavealpha($mask, true);
        imagefill($mask,0,0,$trans);
        $white = imagecolorallocate($mask, 255,255,255);
        imagefilledellipse($mask, $w/2, $h/2, $w, $h, $white);

        // 将 mask 应用到 tmp
        for($i=0;$i<$w;$i++){
            for($j=0;$j<$h;$j++){
                $alpha = (imagecolorat($mask,$i,$j) & 0xFF) == 127 ? 127 : 0;
                $rgba  = imagecolorat($tmp,$i,$j);
                $c = imagecolorsforindex($tmp,$rgba);
                $col = imagecolorallocatealpha($tmp,$c['red'],$c['green'],$c['blue'],$alpha);
                imagesetpixel($tmp,$i,$j,$col);
            }
        }
        imagecopy($im, $tmp, $x, $y, 0,0,$w,$h);
        imagedestroy($src); imagedestroy($tmp); imagedestroy($mask);
    }

    private function badge($im, $x, $y, $text, array $fg, array $bg){
        $padX = 18; $padY = 10; $r = 10; $fs = 22;
        $bbox = imagettfbbox($fs, 0, $this->fonts['medium'], $text);
        $tw = $bbox[2]-$bbox[0]; $th = $bbox[1]-$bbox[7];
        $w = $tw + $padX*2; $h = $th + $padY*2;

        $this->roundedRect($im, ['x'=>$x,'y'=>$y,'w'=>$w,'h'=>$h,'r'=>$r], $bg);
        $this->ttf($im, $fs, $x+$padX, $y+$h-$padY, $fg, $this->fonts['medium'], $text);
    }

    /** 画 5 颗星 + 分数文本（简单版） */
    private function drawStarRow($im, $x, $y, $total, $score)
    {
        $filled = (int)round($score);  // 5.0 -> 5
        $gap = 8; $size = 24;
        for($i=0;$i<$total;$i++){
            $col = $i < $filled ? '#ffe08a' : '#c4d4cf';
            $this->ttf($im, $size, $x + $i*($size+10), $y, $col, $this->fonts['bold'], '★');
        }
        $this->ttf($im, 28, $x + $total*($size+10) + $gap, $y, '#ffffff', $this->fonts['medium'], number_format($score,1));
    }

    /** 文本自动换行，限定行数超出加省略号 */
    private function wrap($text, $font, $size, $maxWidth, $maxLines=3): string
    {
        $words = mb_str_split($text);
        $line = ''; $lines=[];

        foreach($words as $ch){
            $try = $line . $ch;
            $box = imagettfbbox($size, 0, $font, $try);
            $width = $box[2]-$box[0];
            if ($width <= $maxWidth) {
                $line = $try;
            } else {
                $lines[] = $line;
                $line = $ch;
                if (count($lines) >= $maxLines - 1) break;
            }
        }
        if ($line !== '' && count($lines) < $maxLines) $lines[] = $line;

        if (count($lines) >= $maxLines && mb_strlen($text) > mb_strlen(implode('', $lines))) {
            $last = $lines[$maxLines-1];
            // 尾行加省略
            while(true){
                $box = imagettfbbox($size,0,$font,$last.'…');
                if (($box[2]-$box[0]) <= $maxWidth || mb_strlen($last)==0) break;
                $last = mb_substr($last,0,-1);
            }
            $lines[$maxLines-1] = $last.'…';
        }
        // 纵向行距
        $out=''; $lh = $size + 12;
        foreach($lines as $i=>$ln){
            $out .= ($i==0?'':"\n") . $ln;
        }
        return $out;
    }

    private function createFrom($path)
    {
        $ext = strtolower(pathinfo($path, PATHINFO_EXTENSION));
        switch($ext){
            case 'jpg': case 'jpeg': return imagecreatefromjpeg($path);
            case 'png': return imagecreatefrompng($path);
            case 'gif': return imagecreatefromgif($path);
            default: return false;
        }
    }
}